package com.lg.shiro;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.stereotype.Repository;
import org.springframework.util.SerializationUtils;

import com.lg.annotation.JedisClient;

import redis.clients.jedis.Jedis;

@Repository
public class RedisCache<k, V> implements Cache<k, V> {
	private String name;
	private static final String CACHE_PREFIX = "SHIRO:CACHE:";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@SuppressWarnings("unchecked")
	@Override
	@JedisClient
	public V get(k key) throws CacheException {
		Jedis jedis = RedisContext.get();
		// TODO Auto-generated method stub
		String rediskey = getRediskey(key);
		 try {
			byte[] value = jedis.get(rediskey.getBytes());
			return  (V) SerializationUtils.deserialize(value);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public String getRediskey(Object key) {
		if (key == null) {
			throw new RuntimeException("key is null");
		}
	
		return CACHE_PREFIX + key.toString();
	}

	@Override
	@JedisClient
	public V put(k key, V value) throws CacheException {
		// TODO Auto-generated method stub
		Jedis jedis = RedisContext.get();
		try {
			String rediskey = getRediskey(key);
			byte[] vauleS = SerializationUtils.serialize(value);
			jedis.set(rediskey.getBytes(), vauleS);
			jedis.expire(rediskey.getBytes(), 18000);
			return value;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;
	}

	@SuppressWarnings("unchecked")
	@Override
	@JedisClient
	public V remove(k key) throws CacheException {
		// TODO Auto-generated method stub
		Jedis jedis = RedisContext.get();
			String rediskey = getRediskey(key);
			byte[] value = jedis.get(rediskey.getBytes());
			Long del = jedis.del(rediskey.getBytes());
			return  (V) SerializationUtils.deserialize(value);
	}

	@Override
	@JedisClient
	public void clear() throws CacheException {
		// TODO Auto-generated method stub
		Jedis jedis = RedisContext.get();
			Set<byte[]> keys = jedis.keys((CACHE_PREFIX + "*").getBytes());
			jedis.del(keys.toArray(new byte[1][1]));
	}

	@Override
	@JedisClient
	public int size() {
		// TODO Auto-generated method stub
		Jedis jedis =  RedisContext.get();
		try {
			Set<byte[]> keys = jedis.keys((CACHE_PREFIX + "*").getBytes());
			return keys.size();
		} catch (Exception e) {}
		return 0;
	}

	@Override
	@JedisClient
	public Set<k> keys() {
		// TODO Auto-generated method stub
		Jedis jedis = RedisContext.get();
		try {
			Set<byte[]> keys = jedis.keys((CACHE_PREFIX + "*").getBytes());
			Set<k> set = new HashSet<>();
			for (byte[] str : keys) {
				String string = new String(str).substring(CACHE_PREFIX.length());
				k parse = (k) string;
				set.add(parse);
			}

			return set;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	@JedisClient
	public Collection<V> values() {
		// TODO Auto-generated method stub
		Jedis jedis = RedisContext.get();
			Set<byte[]> keys = jedis.keys((CACHE_PREFIX + "*").getBytes());
			List<V> list = new ArrayList<>();
			for (byte[] string : keys) {
				byte[] value = jedis.get(string);
				@SuppressWarnings("unchecked")
				V parse = (V) SerializationUtils.deserialize(value);
				list.add(parse);
			}
			return list;
	}

}
